{
  Copyright 2012, Jameel Halabi

  This unit is part of the BlaiseWave wrapper,
  which is licensed under the BSD 2-Clause license (see licenses/license.txt).
}

unit BW_Master;

{$mode delphi}{$H+}

interface

uses
  BW_Access ,
  BW_Handler,

  LW_Types  ,
  LW_Dyna   ,
  LW_Master ,
  LW_Server ;

type
  TEventCode   = (ecNothing,
                  ecCommand,
                  ecTime,
                  ecSelect,
                  ecRenderDone,

                  // These are available when [mfReceiveNotifications] is set

                  {
                    indicates item motion is about to be computed.
                    eventData is the item id being affected or LWITEM_NULL for all items.
                  }
                  ecNotifyMotionUpdateStarting = $100,

                  {
                    indicates item motion is done being computed.
                    eventData is the item id being affected or LWITEM_NULL for all items.
                  }
                  ecNotifyMotionUpdateComplete,

                  {
                    indicates an object's mesh source has been replaced.
                    This is a more drastic mesh change than just transforming an existing mesh.
                    eventData is the item id the object whose mesh has changed.
                  }
                  ecNotifyMeshReplaced,

                  {
                    indicates a single mesh is about to be transformed.
                    eventData is the object item id being affected.
                    MeshInfo::pntOtherPos() values are not valid at this point.
                  }
                  ecNotifyMeshUpdateStarting,

                  {
                    indicates a mesh vertexes represent their 'after morphing' positions.
                    'eventData' is an item id.
                    MeshInfo::pntOtherPos() values may be used.
                  }
                  ecNotifyMeshUpdateAfterMorphing,

                  {
                    indicates a mesh vertexes represent their 'after bones' positions.
                    'eventData' is an item id.
                    MeshInfo::pntOtherPos() values may be used.
                  }
                  ecNotifyMeshUpdateAfterBones,

                  {
                    indicates a mesh vertexes represent their 'after local displacements' positions.
                    'eventData' is an item id.
                    MeshInfo::pntOtherPos() values may be used.
                  }
                  ecNotifyMeshUpdateAfterLocalDisplacements,

                  {
                    indicates a mesh vertexes represent their 'after motion' positions.
                    'eventData' is an item id.
                    MeshInfo::pntOtherPos() values may be used
                  }
                  ecNotifyMeshUpdateAfterMotion,

                  {
                    indicates a single mesh is done being transformed.
                    eventData is the object item id that was affected.
                    MeshInfo::pntOtherPos() values may be used
                  }
                  ecNotifyMeshUpdateComplete,

                  {
                    indicates a frame is about to be rendered.
                    eventData is the time being rendered.
                  }
                  ecNotifyRenderFrameStarting,

                  {
                    indicates a frame has completed being rendered.
                    eventData is the time being rendered.
                  }
                  ecNotifyRenderFrameComplete = $110,

                  {
                    indicates a sequence of frames are about to be rendered
                  }
                  ecNotifyRenderStarting,

                  {
                    indicates a sequence of frames has completed being rendered.
                    This is the same as LWEVNT_RENDER_DONE with the addition that it occurs in ScreamerNet.
                  }
                  ecNotifyRenderComplete,

                  {
                    indicates a scene is about to be cleared.
                    Of course, an existing master handler needs to exist to detect this.
                    eventData is the name of the scene before it was cleared.
                  }
                  ecNotifySceneClearStarting,

                  {
                    indicates a scene has just been cleared.
                    Only a master handler that survives a scene clear (LAYOUT type)
                    will still be around to detect this.
                    eventData is the name of the scene as it exists as a cleared scene.
                  }
                  ecNotifySceneClearComplete,

                  {
                    indicates a scene is about to be loaded.
                    eventData is the name of the scene file being loaded.
                  }
                  ecNotifySceneLoadStarting,

                  {
                    indicates a scene has just been loaded.
                    eventData is the name of the scene file that was loaded.
                  }
                  ecNotifySceneLoadComplete,

                  {
                    indicates a scene is about to be saved.
                    eventData is the name of the scene being saved.
                  }
                  ecNotifySceneSaveStarting,

                  {
                    indicates a scene has just been saved.
                    eventData is the name of the scene file that was saved.
                  }
                  ecNotifySceneSaveComplete,

                  {
                    indicates an item has been added.
                    eventData is the item id that was added.
                  }
                  ecNotifyItemAdded,

                  {
                    indicates an item is about to be removed.
                    eventData is the item id that is going to be removed.
                  }
                  ecNotifyItemRemoving,

                  {
                    indicates an item has had its parent changed.
                    eventData is the item id that had its parent changed.
                  }
                  ecNotifyItemReParented,

                  {
                    indicates a surface was altered in some way.
                    eventData is a SurfID
                  }
                  ecNotifySurfaceAltered,

                  {
                    These are available when
                    LWMASTF_RECEIVE_NOTIFICATIONS & LWMASTF_RECEIVE_NOTIFICATIONS_MESHPOINTS
                    are set
                  }

                  {
                    This indicates a change to the world position of a vertex in an object was altered.
                    'eventData' is an item ID.
                    The world vertex position can be altered by simple movement or rotation as well.
                    By looking for constant movement and orientation, one can rule out those as being
                    the cause of the alteration.
                  }
                  ecNotifyMeshPointsAltered,

                  {
                    indicates a channel has been added.
                    eventData is the channel id that was added.
                  }
                  ecNotifyChannelAdded, { TODO }

                  {
                    indicates a channel is about to be removed.
                    eventData is the channel id that is going to be removed.
                  }
                  ecNotifyChannelRemoving, { TODO }

                  {
                    indicates a surface has been added.
                    eventData is the surface id that was added.
                  }
                  ecNotifySurfaceAdded,

                  {
                    indicates a surface is about to be removed.
                    eventData is the LWSurfaceID that is going to be removed.
                  }
                  ecNotifySurfaceRemoving,

                  {
                    Indicates a plugin instance has changed.
                    Dependencies on that plugin may wish to be updated and
                    can determine if they truely need to be by receiving this event,
                    comparing the plugin class, and server name.
                    The specific value that changed that caused this event is not
                    pass along however.
                    eventData is a structure that contains information about the
                    instance of the plugin being updated.
                  }
                  ecNotifyPlugInChanged,

                  {
                    sent to clients when the user has aborted the current render
                    by pressing the "Abort" button (or pressing Escape) from the
                    Layout GUI
                  }
                  ecNotifyRenderAborted,

                  {
                    indicates a texture is about to be removed.
                    eventData is the LWTextureID that is going to be removed.
                  }
                  ecNotifyTextureRemoving,

                  {
                    indicates an image clip is about to be removed.
                    eventData is the LWImageID that is going to be removed.
                  }
                  ecNotifyImageRemoving,

                  {
                    indicates image clip settings are being altered such that the resulting
                    image will differ. eventData is the LWImageID that is going to be removed.
                  }
                  ecNotifyImageAltered,

                  {
                    indicates a surface was altered in some way.
                    eventData is a LWTextureID
                  }
                  ecNotifyTextureAltered,

                  {
                    indicates that the internal object list has been reordered in some way
                  }
                  ecNotifyListUpdateObjects,

                  {
                    indicates that the internal light list has been reordered in some way
                  }
                  ecNotifyListUpdateLights,

                  {
                    indicates that the internal camera list has been reordered in some way
                  }
                  ecNotifyListUpdateCameras,

                  {
                    indicates that the internal bone list for an object has been reordered
                    in some way.  eventData is the LWItemID that owns the bones.
                  }
                  ecNotifyListUpdateBones,

                  {
                    indicates an object is about to be saved to a disk file.
                    eventData is the LWItemID of the object item being saved.
                  }
                  ecNotifyObjectSaveStarting,

                  {
                    indicates an object has just been saved to a disk file.
                    eventData is the LWItemID of the object item that was saved.
                  }
                  ecNotifyObjectSaveComplete,
                  {
                    indicates a viewport renderer like VPR has been activated.
                    eventData is null.
                  }
                  ecViewportObjectAdded,
                  {
                    indicates a viewport renderer like VPR has been removed.
                    eventData is null.
                  }
                  ecViewportObjectRemoved,

                  /// The plugin event is one of the following:
                  ecPlugInUpdated = 0,
                  ecPlugInCreated,
                  ecPlugInDestroyed,
                  ecPlugInEnabled,
                  ecPlugInDisabled,
                  ecPlugInDestroying);

  TMasterFlag  = (mfLayout =
                  LWMASTF_LAYOUT                          ,
                  mfReceiveNotifications =
                  LWMASTF_RECEIVE_NOTIFICATIONS           ,
                  mfReceiveNotificationsMeshpoints =
                  LWMASTF_RECEIVE_NOTIFICATIONS_MESHPOINTS) ;
  TMasterFlags = set of TMasterFlag;

  { TMasterAccess }

  TMasterAccess = class(THandlerAccess)
  private
    function  GetEventCode                             : TEventCode   ;
    function  GetEventData                             : Pointer      ;
  public
    function  LookUp
              (      Data    : Pointer               ;
                     CmdName : String                ) : TLWCommandCode;
    function  Execute
              (      Command : String                ;
               const Args    : array of TDynaValueRec) : TDynaValueRec;
    procedure Evaluate
              (const Command : String                ) ;

    property  EventCode : TEventCode read GetEventCode;
    property  EventData : Pointer    read GetEventData;
  end;

  { TMaster }

  TMaster = class(TItemHandler)
  protected
    var
      FMasterAccess : TMasterAccess;

    function  GetHandlerType                   : String      ; override;

    function  HandlerActivate
              (      Local  : Pointer        ) : Integer     ; override;

    function  MasterEvent
              (const Access : PLWMasterAccess) : Double      ;
    function  MasterFlags
              (const Void                    ) : UInt32      ;

  public
    destructor
              Destroy                          ;               override;

    procedure Event                            ;               virtual ;
    function  SetFlags                         : TMasterFlags; virtual ;

    property  Commander : TMasterAccess read  FMasterAccess
                                        write FMasterAccess;
  end;

implementation

{ TMasterAccess }

function  TMasterAccess.GetEventCode                            : TEventCode   ;
begin
  Result := TEventCode(PLWMasterAccess(FAccess).EventCode);
end;

function  TMasterAccess.GetEventData                            : Pointer      ;
begin
  Result := PLWMasterAccess(FAccess).EventData;
end;

function TMasterAccess.LookUp(Data: Pointer; CmdName: String) : TLWCommandCode ;
begin
  Result := PLWMasterAccess(FAccess).Evaluate( PLWMasterAccess(FAccess).Data ,
                                               PChar(CmdName)) ;
end;

function  TMasterAccess.Execute
                        (      Command : String                ;
                         const Args    : array of TDynaValueRec) : TDynaValueRec;
begin
  // TODO : Implement Execute method
end;

procedure TMasterAccess.Evaluate(const Command : String);
begin
  PLWMasterAccess(FAccess).Evaluate(
  PLWMasterAccess(FAccess).Data,    PChar(Command));
end;

{ TMaster }

function  TMaster.GetHandlerType                   : String      ;
begin
  Result := LWMASTER_HCLASS;
end;

function  TMaster.HandlerActivate
                  (      Local  : Pointer        ) : Integer     ;
var
  MasterLocal: PLWMasterHandler absolute Local;
begin
  MasterLocal.Event := Pointer(MasterEvent);
  MasterLocal.Flags := Pointer(MasterFlags);

  Result := AFUNC_OK;
end;

function  TMaster.MasterEvent
                  (const Access : PLWMasterAccess) : Double      ;
begin
  if not Assigned(FMasterAccess) then
    FMasterAccess := TMasterAccess.Create;

  FMasterAccess.Access := Access;

  Result := 0;

  Event;
end;

function  TMaster.MasterFlags
                 (const Void                    ) : UInt32      ;
var
  Index : TMasterFlag;
  Flags : UInt32 = 0 ;
begin
  for Index in SetFlags do
    Flags := Flags or Integer(Index);

  Result := Flags;
end;

destructor
          TMaster.Destroy                         ;
begin
  if Assigned(FMasterAccess) then
    FMasterAccess.Free;

  inherited Destroy;
end;

procedure TMaster.Event                           ;
begin
end;

function  TMaster.SetFlags                        : TMasterFlags;
begin
  Result := [];
end;

end.

